﻿using System;

namespace HamcoWcs.Models.Devices
{
    public static class BitExtension
    {
        public static int ReadBit(this byte b, int pos) =>
            b.ReadBool(pos) ? 1 : 0;

        public static bool ReadBool(this byte b, int pos)
        {
            byte x = 1;
            switch (pos)
            {
                case 0: { x = 0x01; } break;
                case 1: { x = 0x02; } break;
                case 2: { x = 0x04; } break;
                case 3: { x = 0x08; } break;
                case 4: { x = 0x10; } break;
                case 5: { x = 0x20; } break;
                case 6: { x = 0x40; } break;
                case 7: { x = 0x80; } break;
                default:
                    throw new ArgumentOutOfRangeException("pos", "range 0-7");
            }
            return (b & x) == x;
        }

        public static int ReadBit(this byte[] bytes, int offset, int pos) =>
            bytes.ReadBool(offset, pos) ? 1 : 0;

        public static bool ReadBool(this byte[] bytes, int offset, int pos)
        {
            if (offset < 0 || offset >= bytes.Length) throw new ArgumentOutOfRangeException("offset", "Range:0 <= offset < bytes.Length");

            return bytes[offset].ReadBool(pos);
        }


        /// <summary>
        /// 设置字节中的制定Bit
        /// </summary>
        /// <param name="b">字节</param>
        /// <param name="index">bit索引 [0,7]</param>
        /// <param name="value">true:1,false:0</param>
        /// <returns></returns>
        public static byte SetBit(this byte b, int index, bool value)
        {
            if (value)
            {
                switch (index)
                {
                    case 0: { return b |= 0x01; }
                    case 1: { return b |= 0x02; }
                    case 2: { return b |= 0x04; }
                    case 3: { return b |= 0x08; }
                    case 4: { return b |= 0x10; }
                    case 5: { return b |= 0x20; }
                    case 6: { return b |= 0x40; }
                    case 7: { return b |= 0x80; }
                    default: { return b; }
                }
            }
            else
            {
                switch (index)
                {
                    case 0: { return b &= 0xFE; }
                    case 1: { return b &= 0xFD; }
                    case 2: { return b &= 0xFB; }
                    case 3: { return b &= 0xF7; }
                    case 4: { return b &= 0xEF; }
                    case 5: { return b &= 0xDF; }
                    case 6: { return b &= 0xBF; }
                    case 7: { return b &= 0x7F; }
                    default: { return b; }
                }
            }
        }

        /// <summary>
        /// 设置字节中的制定Bit
        /// </summary>
        /// <param name="b">字节</param>
        /// <param name="index">bit索引 [0,7]</param>
        /// <param name="value">(0,1)</param>
        /// <returns></returns>
        public static byte SetBit(this byte b, int index, int value)
        {
            if (value < 0 || value > 1) return b;
            return b.SetBit(index, value == 1);
        }
    }
}
